package edu.yngsxy.dsstudyApi.core.security;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.stp.StpInterface;
import cn.hutool.core.convert.Convert;
import edu.yngsxy.dsstudyApi.core.util.WkRedisService;
import edu.yngsxy.dsstudyApi.sys.model.dto.SysRoleDTO;
import edu.yngsxy.dsstudyApi.sys.model.dto.SysUserDTO;
import edu.yngsxy.dsstudyApi.sys.model.entity.SysPermission;
import edu.yngsxy.dsstudyApi.sys.service.SysRoleService;
import edu.yngsxy.dsstudyApi.sys.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 自定义权限加载接口实现类
 */
@Component    // 保证此类被 SpringBoot 扫描，完成 Sa-Token 的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {
    @Autowired
    SysUserService sysUserService;
    /**
     * 返回一个账号所拥有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        // 本 list 仅做模拟，实际项目中要根据具体业务逻辑来查询权限
        /*
        if (loginId.equals("10002")) {
            List<String> list = new ArrayList<String>();
            list.add("user:get");
            list.add("codegen:gen");
            list.add("role:*");//role模块下所有权限
            return list;
        }
        return new ArrayList<String>();//其他账号无任何权限
        */
        // 1. 声明权限码集合
        List<String> list = new ArrayList<>();

        // 2. 遍历角色列表，查询拥有的权限码
        for (String role : getRoleList(loginId, loginType)) {//role 是角色码 如user
            System.out.println("用户拥有的角色："+role);
            List<String> permissionList = (List<String>) SaManager.getSaTokenDao().getObject("wktoken:role-find-permission:" + role);
            System.out.println("角色拥有的权限：");
            permissionList.forEach(System.out::println);
            Optional.ofNullable(permissionList).ifPresentOrElse(list::addAll, () -> {});
            //list.addAll(permissionList);
        }

        // 3. 返回权限码集合
        return list;
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        // 本 list 仅做模拟，实际项目中要根据具体业务逻辑来查询角色
        /*
        if (loginId.equals("10002")) {
            List<String> list = new ArrayList<String>();
            list.add("admin");
            return list;
        }
        return new ArrayList<>();*/
        //从缓存中获取某个用户的角色列表
        List<String> roleList = (List<String>) SaManager.getSaTokenDao().getObject("wktoken:loginId-find-role:" + loginId);
        if (roleList == null) {//缓存没有角色
            // 从数据库查询这个账号id拥有的角色列表，
            System.out.println("用户拥有的角色");
            SysUserDTO obj = sysUserService.selectWithRolePermissionByUserId(Convert.toLong(loginId));
            roleList = new ArrayList<>();
            for (SysRoleDTO role : obj.getRoles()) {//循环数据库角色列表
                roleList.add(role.getCode().toLowerCase());
                System.out.println("---------角色："+role.getCode());
                List<String> perms = new ArrayList<>();//角色对应的权限列表（字符串权限码）
                System.out.println("角色拥有的权限");
                for (SysPermission permission : role.getPermissions()) {//循环角色对应的权限列表
                    perms.add(permission.getCode().toLowerCase());
                    System.out.println("--------权限："+permission.getCode());
                }
                //将角色码对应的权限列表也加入到缓存中
                SaManager.getSaTokenDao().setObject("wktoken:role-find-permission:" + role.getCode(), perms , 60 * 60 * 24 * 30);
            }
            // 查好后，将某个用对应的角色列表也存入到缓存中
            SaManager.getSaTokenDao().setObject("wktoken:loginId-find-role:" + loginId, roleList, 60 * 60 * 24 * 30);
        }
        return roleList;
    }

    /**
     * 刷新权限列表
     */
    public static void refreshRolePermissionList(SysRoleService sysRoleService, WkRedisService redisService) {
        //遍历角色及权限，清空缓存
        redisService.deleteKeysByPattern("wktoken:loginId-find-role:*");
        redisService.deleteKeysByPattern("wktoken:role-find-permission:*");
        List<SysRoleDTO> rolse = sysRoleService.selectAllWithPermissions();
        for (SysRoleDTO role : rolse) {
            List<String> perms = new ArrayList<>();//角色对应的权限列表（字符串权限码）
            for (SysPermission permission : role.getPermissions()) {//循环角色对应的权限列表
                Optional.ofNullable(permission.getCode()).ifPresent(perm_code -> perms.add(perm_code.toLowerCase()) );
            }
            //将角色码对应的权限列表也加入到缓存中
            SaManager.getSaTokenDao().setObject("wktoken:role-find-permission:" + role.getCode(), perms , 60 * 60 * 24 * 30);
        }
    }

}

